<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-'>/**
</span> * @ignore
 * checkable tree node
 * @author yiminghe@gmail.com
 */
KISSY.add(&quot;tree/check-node&quot;, function (S, Node, TreeNode) {
    var $ = Node.all,
        PARTIAL_CHECK = 2,
        CHECK = 1,
        EMPTY = 0;

<span id='KISSY-Tree-CheckNode'>    /**
</span>     * Checked tree node. xclass: 'check-tree-node'.
     * @class KISSY.Tree.CheckNode
     * @extends KISSY.Tree.Node
     */
    var CheckNode = TreeNode.extend({
        handleClickInternal: function (e) {
            var self = this,
                checkState,
                expanded = self.get(&quot;expanded&quot;),
                expandIconEl = self.get(&quot;expandIconEl&quot;),
                tree = self.get(&quot;tree&quot;),
                target = $(e.target);

            // 需要通知 tree 获得焦点
            tree.focus();

            // 点击在 +- 号，切换状态
            if (target.equals(expandIconEl)) {
                self.set(&quot;expanded&quot;, !expanded);
                return;
            }

            // 单击任何其他地方都切换 check 状态
            checkState = self.get(&quot;checkState&quot;);

            if (checkState == CHECK) {
                checkState = EMPTY;
            } else {
                checkState = CHECK;
            }


            self.set(&quot;checkState&quot;, checkState);

           self.fire(&quot;click&quot;);
            return true;
        },

        _onSetCheckState: function (s) {
            var self = this,
                parent = self.get('parent'),
                checkCount,
                i,
                c,
                cState,
                cs;

            if (s == CHECK || s == EMPTY) {
                S.each(self.get(&quot;children&quot;), function (c) {
                    c.set(&quot;checkState&quot;, s);
                });
            }

            // 每次状态变化都通知 parent 沿链检查，一层层向上通知
            // 效率不高，但是结构清晰
            if (parent) {
                checkCount = 0;
                cs = parent.get(&quot;children&quot;);
                for (i = 0; i &lt; cs.length; i++) {
                    c = cs[i];
                    cState = c.get(&quot;checkState&quot;);
                    // 一个是部分选，父亲必定是部分选，立即结束
                    if (cState == PARTIAL_CHECK) {
                        parent.set(&quot;checkState&quot;, PARTIAL_CHECK);
                        return;
                    } else if (cState == CHECK) {
                        checkCount++;
                    }
                }

                // 儿子都没选，父亲也不选
                if (checkCount === 0) {
                    parent.set(&quot;checkState&quot;, EMPTY);
                } else
                // 儿子全都选了，父亲也全选
                if (checkCount == cs.length) {
                    parent.set(&quot;checkState&quot;, CHECK);
                }
                // 有的儿子选了，有的没选，父亲部分选
                else {
                    parent.set(&quot;checkState&quot;, PARTIAL_CHECK);
                }
            }
        }
    }, {
        ATTRS:{
            checkIconEl: {
            },

            checkable: {
                value: true,
                view: 1
            },

<span id='KISSY-Tree-CheckNode-property-checkState'>            /**
</span>             * Enums for check states.
             * CheckNode.PARTIAL_CHECK: checked partly.
             * CheckNode.CHECK: checked completely.
             * CheckNode.EMPTY: not checked.
             * @type {Number}
             */
            checkState: {
                // check 的三状态
                // 0 一个不选
                // 1 儿子有选择
                // 2 全部都选了
                value: 0,
                sync: 0,
                view: 1
            },

            defaultChildCfg: {
                value: {
                    xclass: 'check-tree-node'
                }
            }
        },
        xclass: &quot;check-tree-node&quot;
    });

<span id='KISSY-Tree-CheckNode-CheckState'>    /**
</span>     * check node's check state enum
     * @enum {Number} KISSY.Tree.CheckNode.CheckState
     */
    CheckNode.CheckState={
<span id='KISSY-Tree-CheckNode-CheckState-property-PARTIAL_CHECK'>        /**
</span>         * checked partly.
         */
        PARTIAL_CHECK: PARTIAL_CHECK,
<span id='KISSY-Tree-CheckNode-CheckState-property-CHECK'>        /**
</span>         * checked completely.
         */
        CHECK: CHECK,
<span id='KISSY-Tree-CheckNode-CheckState-property-EMPTY'>        /**
</span>         * not checked at all.
         */
        EMPTY: EMPTY
    };

    return CheckNode;
}, {
    requires: ['node', './node']
});</pre>
</body>
</html>
